import java.io.File;
import java.io.IOException;
import java.util.List;

import org.junit.Test;

import rsi.mesoscopic.util.DiskSwap;

import junit.framework.TestCase;

public class TestDiskSwap extends TestCase {

	private File mValidDirectory = new File(".diskSwapTests");
	
	@Override
	protected void setUp() throws Exception {

		if(!mValidDirectory.exists()) {
			mValidDirectory.mkdir();
		}
		
		if(!mValidDirectory.canWrite()) {
			fail("Cannot test DiskSwap constructor since it was not possible to create a directory with write access: " + mValidDirectory);
		}
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
	}
	
	@Test
	public void testConstructor() {
		//Use a directory where user cannot has write permission access
		File noPermissionDirectory = new File("/");
		DiskSwap<String> diskSwap;
		try {
			diskSwap = new DiskSwap<String>(noPermissionDirectory);
			
			//Release diskswap
			diskSwap.release();
			
			//If test reachs this line, something is wrong
			fail("DiskSwap constructor must throw an exception when a directory with no write access is informed: " + noPermissionDirectory);
		} catch (IOException e) {
			//Everything ok
		}
		
		//Use a valid directory		
		try {
			diskSwap = new DiskSwap<String>(mValidDirectory);
			diskSwap.release();
		} catch (IOException e) {
			fail("Cannot create a valid disk swap dir with a valid directory: " + mValidDirectory + " - " + e.getMessage());
		}
	}
	
	@Test
	public void testAppend() throws IOException {
		//Append 1 element
		DiskSwap<String> diskSwap = new DiskSwap<String>(mValidDirectory);
		String element = "Test1";
		diskSwap.append(element);
		
		List<String> result = diskSwap.get(1);
		assertEquals(1, result.size());
		
		assertEquals("Cannot retrieve an appended element.", element, result.get(0));
		diskSwap.release();
		
		//Append a large amount
		diskSwap = new DiskSwap<String>(mValidDirectory);
		for(int i = 0; i < 500; i++) {
			diskSwap.append("Test"+i);
		}
		
		int blockSize = 100;
		List<String> t;
		for(int i = 0; i < 500/blockSize; i++) {
			t = diskSwap.get(blockSize);
			
			for(int j = 0; j < blockSize; j++) {
				assertEquals("Cannot retrieve an appended element.", "Test"+(blockSize*i+j), t.get(j));
			}
		}
		diskSwap.release();
	}
	
	@Test
	public void testGet() throws IOException {
		DiskSwap<String> diskSwap = new DiskSwap<String>(mValidDirectory);
		
		//Get an invalid element
		try {
			List<String> result = diskSwap.get(1);
			
			assertEquals(0, result.size());
		}
		catch(Exception e){
			//If exception could be caught, everything is all right
		}
		
		//Get a valid element
		diskSwap.append("Test");
		
		List<String> result = diskSwap.get(1);
		
		assertEquals("Invalid result array size", 1, result.size());
		assertEquals("Cannot retrieve correct value", "Test", result.get(0));
		diskSwap.release();
		
		//Get 10 elements
		diskSwap = new DiskSwap<String>(mValidDirectory);
		
		for(int i = 0; i < 100; i++) {
			diskSwap.append("Test"+i);
		}
		
		result = diskSwap.get(10);
		
		for(int i = 0; i < 10; i++){
			assertEquals("Test"+i, result.get(i));
		}
		
		diskSwap.release();
		
		//Get 0 elements
		diskSwap = new DiskSwap<String>(mValidDirectory);
		
		diskSwap.append("Test");
		
		result = diskSwap.get(0);
		assertEquals("A get operation with 0 as parameter should return an empty array", 0, result.size());
		
		result = diskSwap.get(1);
		assertEquals("A get operation with 0 as paramter should no move swap pointer", 1, result.size());
		assertEquals("Test", result.get(0));
		
		diskSwap.release();
		
		//Get with more elements than have on vector
		diskSwap = new DiskSwap<String>(mValidDirectory);
		
		for(int i = 0; i < 10; i++) {
			diskSwap.append("Test"+i);
		}
		
		result = diskSwap.get(20);
		assertEquals(10, result.size());
		
		for(int i = 0; i < 10; i++) {
			assertEquals("Test"+i, result.get(i));
		}
		
		diskSwap.release();
	}
	
	@Test
	public void testSeek() throws IOException {
		//Test seek to 0
		DiskSwap<String> diskSwap = new DiskSwap<String>(mValidDirectory);
		
		for(int i = 0; i < 10; i++) {
			diskSwap.append("Test"+i);
		}
		
		List<String> result = diskSwap.get(10);
		
		assertNotNull(result);
		assertEquals(10, result.size());
		
		for(int i = 0; i < 10; i++) {
			assertEquals("Test"+i, result.get(i));
		}
		
		diskSwap.seek(0);
		
		result = diskSwap.get(10);
		assertNotNull(result);
		
		for(int i = 0; i < 10; i++) {
			assertEquals("Test"+i, result.get(i));
		}
		
		diskSwap.release();
	}
}
